<script lang="ts" setup>
  import { message } from 'ant-design-vue'
  import { Modal } from 'ant-design-vue'
  import md5 from 'js-md5'
  import { reactive, ref } from 'vue'
  import { useRouter } from 'vue-router'

  import { requestUpdatePwd } from '/@/api/system/ysys-user/unAuth/account'
  import { requestCheckEmailCode, requestCheckSmsCode, requestSendEmailLoginCode, requestSendSmsCode } from '/@/api/system/ysys-user/unAuth/sms'
  import { HttpCodeEnum } from '/@/enums/httpEnum'
  import { RouterPathEnum } from '/@/enums/routerEnum'

  const router = useRouter()
  const activeKey = ref(0)
  const step = ref(0)
  const tabs = [
    {
      ind: 0,
      key: 10,
      title: '手机号',
      phone: '',
      phoneCode: '',
      sendCode: async () => {
        const { responseCode } = await requestSendSmsCode({ phoneNum: state.phone })
        return { responseCode }
      },
      checkCode: async () => {
        const { responseCode, responseData } = await requestCheckSmsCode({
          phoneNum: state.phone,
          smsCode: state.phoneCode,
        })
        return { responseCode, responseData }
      },
    },
    {
      ind: 1,
      key: 20,
      title: '邮箱',
      phone: '',
      phoneCode: '',
      sendCode: async () => {
        const { responseCode } = await requestSendEmailLoginCode({ email: state.phone })
        return { responseCode }
      },
      checkCode: async () => {
        const { responseCode, responseData } = await requestCheckEmailCode({
          email: state.phone,
          emailCode: state.phoneCode,
        })
        return { responseCode, responseData }
      },
    },
  ]
  const state = reactive({
    loading: false,
    phone: '',
    phoneCode: '',
    pwd: '',
    pwdAgain: '',
    tempCode: '', // 校验验证码返回的临时验证码，修改密码接口用
  })

  const secondTip = ref<number>(0)

  /**
   * 获取短信验证码
   */
  const getPhoneCode = async () => {
    if (secondTip.value) return
    if (state.phone === '') {
      message.error(`请输入${tabs[activeKey.value].title}`)
      return
    }
    const { responseCode } = await tabs[activeKey.value].sendCode()
    if (responseCode === HttpCodeEnum.SUCCESS) resetSecond()
  }

  /**
   * 验证码重置及倒计时
   */
  const resetSecond = async () => {
    secondTip.value = 60
    const intervalId = setInterval(() => {
      if (secondTip.value > 0) {
        secondTip.value--
      } else {
        clearInterval(intervalId)
      }
    }, 1000)
  }

  /**
   * 校验
   * @returns
   */
  const valid = () => {
    const regex = /^(?![\d]+$)(?![a-zA-Z]+$)(?![^\da-zA-Z\s]+$)\S{6,20}$/
    if (state.pwd === '') {
      message.error('请输入密码')
      return false
    }
    if (!regex.test(state.pwd)) {
      message.error('密码需6-20位字母、数字、特殊字符至少两种组合，不能包含空格')
      return false
    }
    if (state.pwdAgain === '') {
      message.error('请再次输入密码')
      return false
    }
    if (state.pwd !== state.pwdAgain) {
      message.error('两次密码不一致')
      return false
    }
    return true
  }

  const validStep1 = () => {
    if (state.phone === '') {
      message.error(`请输入${tabs[activeKey.value].title}`)
      return false
    }
    if (state.phoneCode === '') {
      message.error('请输入验证码')
      return false
    }
    return true
  }

  /**
   * 修改手机号
   */
  const updatePwd = async () => {
    if (!valid()) return
    state.loading = true
    const { responseCode } = await requestUpdatePwd({
      userPwd: md5(state.pwd),
      tempCode: state.tempCode,
      phoneNum: state.phone,
    })
    state.loading = false
    if (responseCode === HttpCodeEnum.SUCCESS) {
      step.value++
      Modal.warning({
        title: '提示',
        content: '您的密码已重置，请重新登录',
        onOk() {
          doLogin()
        },
      })
    }
  }

  const doLogin = async () => {
    router.push(RouterPathEnum.LOGIN)
  }

  const next = async () => {
    if (!validStep1()) return
    state.loading = true
    const { responseCode, responseData } = await tabs[activeKey.value].checkCode()
    if (responseCode === HttpCodeEnum.SUCCESS) {
      state.tempCode = responseData
      step.value++
    }
    state.loading = false
  }
  const prev = async () => {
    step.value--
  }

  // 切换面板
  const changePane = (index) => {
    // 切换tab保留各自的输入值
    let ind = index === 1 ? 0 : 1
    tabs[ind].phone = state.phone
    tabs[ind].phoneCode = state.phoneCode
    state.phone = tabs[index].phone
    state.phoneCode = tabs[index].phoneCode
    state.pwd = ''
    state.pwdAgain = ''
    secondTip.value = 0
    step.value = 0
  }
</script>

<template>
  <div class="forgot">
    <div class="content">
      <div class="forgot-title">重置密码</div>
      <a-steps :current="step" progress-dot>
        <a-step title="验证账号" />
        <a-step title="设置新密码" />
        <a-step title="密码重置成功" />
      </a-steps>
      <a-tabs class="mt48" v-model:activeKey="activeKey" @change="changePane">
        <!-- disabled 进入到步骤2时不能切换tab -->
        <a-tab-pane v-for="tab in tabs" :key="tab.ind" :tab="tab.title" :disabled="step" />
      </a-tabs>
      <template v-if="!step">
        <div class="content-label mt24">{{ tabs[activeKey].title }}</div>
        <a-input class="content-input mt12" autocomplete="off" type="text" v-model:value="state.phone" :placeholder="`请输入${tabs[activeKey].title}`" :maxlength="activeKey === 0 ? 11 : 320" />
        <div class="content-label mt24">{{ activeKey === 0 ? '短信' : '邮箱' }}验证码</div>
        <a-input class="content-input mt4" v-model:value="state.phoneCode" :placeholder="`请输入${activeKey === 0 ? '短信' : '邮箱'}验证码`">
          <template #suffix>
            <a class="content-code" @click="getPhoneCode()">{{ secondTip ? `${secondTip}秒` : `获取验证码` }}</a>
          </template>
        </a-input>
        <a-button class="content-button mt48" type="primary" block :loading="state.loading" @click="() => next()">下一步</a-button>
      </template>
      <template v-else>
        <div class="content-label mt24">密码</div>
        <a-input-password autocomplete="off" class="content-input" v-model:value="state.pwd" placeholder="请设置6-20位登录密码" />
        <div class="content-label mt24">确认密码</div>
        <a-input-password autocomplete="off" auto class="content-input" v-model:value="state.pwdAgain" placeholder="请再次输入6-20位登录密码" />
        <a-row class="mt48">
          <a-col :span="12">
            <a-button class="content-button ghost" type="primary" block @click="() => prev()">上一步</a-button>
          </a-col>
          <a-col :span="12">
            <a-button class="content-button" type="primary" block :loading="state.loading" @click="() => updatePwd()">确认</a-button>
          </a-col>
        </a-row>
      </template>

      <div class="register-container">
        <span><a class="login-link" @click="() => doLogin()">返回账号登录</a></span>
      </div>
    </div>
    <div class="copyright">Copyright 2024 @ 云海链控股股份有限公司 琼ICP备19003338号-3</div>
  </div>
</template>

<style lang="less" scoped>
  .forgot {
    width: 100vw;
    min-height: 100vh;
    background: url('/@/assets/images/sys/login/login/bg.png') no-repeat;
    background-size: cover;
    display: flex;
    justify-content: center;
    align-items: center;
  }

  ::v-deep(.ant-input) {
    background: transparent !important;
    color: rgb(255 255 255 / 85%);
    box-shadow: none;

    &::placeholder {
      color: rgb(255 255 255 / 25%);
    }
  }

  ::v-deep(.ant-input-suffix) {
    span {
      color: #fff;
    }
  }

  .content {
    position: relative;
    display: flex;
    flex-direction: column;
    padding: 44px 54px 20px;
    width: 440px;
    height: 620px;
    background: url('/@/assets/images/sys/login/login/login-container.png') no-repeat;
    border-radius: 12px;
    z-index: 2;

    .mt48 {
      margin-top: 48px;
    }

    .forgot-title {
      text-align: center;
      font-size: 20px;
      font-weight: 500;
      color: rgb(255 255 255 / 85%);
      margin-bottom: 40px;
    }

    :deep(.ant-tabs-tab) {
      color: #fff;
    }

    :deep(.ant-tabs-top > .ant-tabs-nav::before) {
      border-bottom: none;
    }

    :deep(.ant-steps-item-title) {
      color: rgb(255 255 255 / 65%) !important;
      font-size: 14px;
    }

    :deep(.ant-steps) {
      position: relative;
      left: -40px;
    }

    :deep(.ant-steps-item) {
      width: 130px;
    }

    :deep(.ant-steps-dot .ant-steps-item-tail) {
      top: 4px;
    }

    :deep(.ant-steps-item-tail::after) {
      height: 1px;
      background-color: #4e5969;
    }

    :deep(.ant-steps-item-active .ant-steps-item-title) {
      color: #13c2c2 !important;
    }

    :deep(.ant-steps-item-wait .ant-steps-item-icon > .ant-steps-icon .ant-steps-icon-dot) {
      background: rgb(255 255 255 / 65%);
    }

    .content-label {
      font-size: 16px;
      font-weight: 500;
      color: rgb(255 255 255 / 85%);
    }

    .content-input {
      border: none;
      border-bottom: 1px solid #4e5969;
      background: transparent;
      font-size: 14px;
      font-weight: 400;
      padding-left: 0;
      box-shadow: none;
    }

    .register-container {
      display: flex;
      flex-direction: row;
      justify-content: center;
      color: rgb(255 255 255 / 45%);
      margin-top: 24px;

      .login-link {
        font-weight: 400;
        color: #13c2c2;
      }
    }

    .content-button {
      width: 100%;
      height: 44px;
      color: #002329;
      background: linear-gradient(90deg, #36cfc9 0%, #13c2c2 100%);

      &.ghost {
        background: transparent;
        color: #13c2c2;
        width: calc(100% - 8px);
      }
    }
  }

  .copyright {
    position: absolute;
    left: 50%;
    bottom: 40px;
    transform: translate(-50%, 0);
    color: rgb(255 255 255 / 65%);
    font-size: 12px;
    z-index: 1;
  }
</style>
